package com.ruoyi.common.utils;

import com.ruoyi.common.constant.HttpStatus;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author Administrator
 */
public class HrWebServiceUtil {

    private static final Logger logger = LoggerFactory.getLogger(HrWebServiceUtil.class);

    /**
     * 域名，这是在server定义的
     */
    private static final String NAMESPACE = "http://tempuri.org/";

    /**
     * 调用方法名Action地址
     */
    private static final String ACTION_URL = "GetToken";

    /**
     * soapAction
     */
    private static final String SOAP_ACTION = NAMESPACE + ACTION_URL;


    /**
     * 获取Hrtoken
     * @param userCode 工号
     * @param expDate 失效时间/天
     * @return
     */
    public static String getHrToken (String userCode,int expDate,String hrWebServiceUrl){
        logger.info("获取hr token的地址为 ：{}",hrWebServiceUrl);
        String message = splicingMessage(NAMESPACE, userCode, expDate);
        String oaToken = getTokenFromHr(message, hrWebServiceUrl);
        logger.info("返回值OAToken: {}",oaToken);
        return oaToken;
    }
    /**
     * 访问webservice接口
     * @param namespace 命名空间
     * @param userCode 入参，用户工号
     * @param expDate 入参，入参失效时间/天
     * @return 返回值
     */
    private static String splicingMessage(String namespace, String userCode, int expDate) {
        StringBuilder sb = new StringBuilder("<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" ");
        sb.append("xmlns:tem=\"");
        sb.append(namespace);
        sb.append("\">\n");
        sb.append("  <soap:Header/>\n");
        sb.append("     <soap:Body>\n");
        sb.append("        <tem:GetToken>\n");
        sb.append("            <tem:UserCode>");
        sb.append(userCode);
        sb.append("</tem:UserCode>\n");
        sb.append("            <tem:ExpirDate>");
        sb.append(expDate);
        sb.append("</tem:ExpirDate>\n");
        sb.append("        </tem:GetToken>\n");
        sb.append("     </soap:Body>\n");
        sb.append("</soap:Envelope>\n");
        return sb.toString();
    }





    /**
     * 获取Hr token
     * @param message 入参的信息
     * @param tarUrl 地址
     * @return 返回token
     */
    private static String getTokenFromHr(String message, String tarUrl) {
        HttpURLConnection conn = null;
        try {
            logger.info("开始访问HR获取Token接口，入参xml为：{}",message);
            URL url = new URL(tarUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setUseCaches(false);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setRequestProperty("Content-Length", Integer.toString(message.length()));
            conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
            conn.setRequestProperty("SOAPAction", SOAP_ACTION);
            OutputStream os = conn.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);
            osw.write(message);
            osw.flush();
            osw.close();
            int code = conn.getResponseCode();
             // 获取响应码 200=成功,当响应成功，获取响应的流
            if (code == HttpStatus.SUCCESS) {
                logger.info("访问HR获取Token接口成功,返回响应码为200");
                StringBuilder sTotalString = new StringBuilder();
                String sCurrentLine;
                InputStream is = conn.getInputStream();
                BufferedReader bReader = new BufferedReader(new InputStreamReader(is));
                while ((sCurrentLine = bReader.readLine()) != null) {
                    sTotalString.append(sCurrentLine);
                }
                bReader.close();
                os.close();
                is.close();
                String sTotal = sTotalString.toString();
                logger.info("访问HR获取Token成功接口,结果值为   {}", sTotal);
                SAXReader reader = new SAXReader();
                InputStream in = new ByteArrayInputStream(sTotal.getBytes(StandardCharsets.UTF_8));
                Document doc = reader.read(in);
                Element rootElement = doc.getRootElement();
                Map<String, Object> map = new HashMap<>();
                getElement(rootElement, map);
                Object getTokenResult = map.get("GetTokenResult");
                if (getTokenResult != null) {
                    String token = getTokenResult.toString();
                    logger.info("访问HR获取Token接口成功，token为 {}",token);
                    return token;
                } else {
                    logger.error("访问HR获取Token接口成功,但是解析没有token");
                    return null;
                }

            } else {
                logger.info("访问HR获取Token接口失败，返回响应码为{}",code);
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("访问HR获取Token接口，发生错误  {}",e.getMessage());
            return null;
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }


    /**
     * 递归遍历返回值xml节点
     * @param root 根节点
     * @param map 结果集
     */
    private static void getElement(Element root, Map<String, Object> map) {
        if (root.elements() != null) {
            //如果当前跟节点有子节点，找到子节点
            List<Element> list = root.elements();
            //遍历每个节点
            for (Element e : list) {
                if (e.elements().size() > 0) {
                    //当前节点不为空的话，递归遍历子节点；
                    getElement(e, map);
                }
                if (e.elements().size() == 0) {
                    //如果为叶子节点，那么直接把名字和值放入map
                    map.put(e.getName(), e.getTextTrim());
                }
            }
        }
    }
}


